/**
 *  This file is part of Bioinformatics Sequence Comparison Game.
 *
 *  Bioinformatics Sequence Comparison Game is free software: you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation, either version 3 of the License, or
 *  (at your option) any later version.
 *
 *  Bioinformatics Sequence Comparison Game is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with Bioinformatics Sequence Comparison Game.  If not, see <http://www.gnu.org/licenses/>.
 *  
 *  @author Eric Augustine
 *  @author Jim Jensen
 *  @author Spencer Vanderpoel
 *  @author Corban McCammon
 *  @author Brett Penza
 *  @version 0.1.1
 */
package com.project.BSCG1;

import java.util.ArrayList;
import java.util.HashMap;
import android.app.Activity;
import android.app.AlertDialog;
import android.content.DialogInterface;
import android.content.Intent;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;

/*
 * Runs the main game for multiplayer mode
 */
public class MultiplayerActivity extends Activity{
	
	private TextView userName; //Text field that contains the user's name
	private TextView p2Name; //Text field for the person in player2's position in the XML
	private TextView p3Name; //Text field for the person in player3's position in the XML
	private TextView p4Name; //Text field for the person in player4's position in the XML
	private Game game; //Game Data structure associated with this activity
	private Button Deck; //Button that activates deck related functionality (i.e drawing)
	private Button DiscardPile; //Button for discard related functionality (i.e discarding, drawing)
	private Button knock; //Button for initiating a knock
	private boolean knockInitiated = false; //Keeps track of any knocks
	private TextView currentScore; //Holds the current players score
	private TextView p2Score; //Holds the score for the person in player2's position
	private TextView p3Score; //Holds the score for the person in player3's position
	private TextView p4Score; //Holds the score for the person in player4's position
	private int currentPlayer = 0; //Holds the current player's turn
	private int numOfCardsToDraw; //Holds the number of cards that each player needs to draw based on the num of players
	private ArrayList<Button> cards; //All the buttons for the current players cards in a list
	private ArrayList<Button> p2Cards; //All buttons for the person in player2's position
	private ArrayList<Button> p3Cards; //All buttons for the person in player3's position
	private ArrayList<Button> p4Cards; //All buttons for the person in player4's position
	private ArrayList<String> playerNames; //Reads in initial player names from previous activity
	private int cardsToEnd; //Cards needed to end the game
	private boolean deckClicked = false; //Whether the deck was clicked
	private HashMap<String, Integer> drawables = new HashMap<String, Integer>();// links amino String to its drawable identity
	private Score score; //Holds score map for the game
	private boolean tutorialMode; //Holds whether tutorial mode is enabled or disabled
	
	/*
	 * Sets up the layout for the game and starts the game
	 */
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        
        //Get the intent
    	Intent main = getIntent();
        
    	//And grab the bundle containing the user information out of it
    	Bundle userInfo = main.getExtras();
        
    	//Get the userName out of the bundle
        playerNames = userInfo.getStringArrayList("playerNames");
        tutorialMode = userInfo.getBoolean("TutorialMode");
        

        /*
         * Initializes the layout, cardsToDraw and cardsToEnd based on
         * the number of players
         */
        switch(playerNames.size()){
        	case 2:
        		numOfCardsToDraw = 6;
        		cardsToEnd = 12;
        		setContentView(R.layout.twoplayergame);
        		break;
        	case 3:
        		cardsToEnd = 10;
        		numOfCardsToDraw = 5;
        		setContentView(R.layout.threeplayergame);
        		break;
        	case 4:
        		cardsToEnd = 8;
        		numOfCardsToDraw = 4;
        		setContentView(R.layout.fourplayergame);
        		break;
        }
        
        findButtons(); //Initializes all of the needed TextViews and Buttons for the game
        
		startGame(); //Start game
    }
    
    /*
     * Initializes all of the games buttons and textViews based on the number of players
     */
    private void findButtons(){
    	Deck = (Button)findViewById(R.id.Deck);
    	DiscardPile = (Button)findViewById(R.id.DiscardPile);
    	knock = (Button)findViewById(R.id.knock);
    	
    	switch(playerNames.size()){
	    	case 2:
	    		p2Name = (TextView)findViewById(R.id.P2Name);
	        	p2Score = (TextView)findViewById(R.id.P2CurrentScore);
	        	cards = new ArrayList<Button>();
	        	cards.add((Button)findViewById(R.id.Card1));
	        	cards.add((Button)findViewById(R.id.Card2));
	        	cards.add((Button)findViewById(R.id.Card3));
	        	cards.add((Button)findViewById(R.id.Card4));
	        	cards.add((Button)findViewById(R.id.Card5));
	        	cards.add((Button)findViewById(R.id.Card6));
	        	cards.add((Button)findViewById(R.id.Card7));
	        	cards.add((Button)findViewById(R.id.Card8));
	        	cards.add((Button)findViewById(R.id.Card9));
	        	cards.add((Button)findViewById(R.id.Card10));
	        	cards.add((Button)findViewById(R.id.Card11));
	        	cards.add((Button)findViewById(R.id.Card12));
	        	p2Cards = new ArrayList<Button>();
	        	p2Cards.add((Button)findViewById(R.id.P2Card1));
	        	p2Cards.add((Button)findViewById(R.id.P2Card2));
	        	p2Cards.add((Button)findViewById(R.id.P2Card3));
	        	p2Cards.add((Button)findViewById(R.id.P2Card4));
	        	p2Cards.add((Button)findViewById(R.id.P2Card5));
	        	p2Cards.add((Button)findViewById(R.id.P2Card6));
	        	p2Cards.add((Button)findViewById(R.id.P2Card7));
	        	p2Cards.add((Button)findViewById(R.id.P2Card8));
	        	p2Cards.add((Button)findViewById(R.id.P2Card9));
	        	p2Cards.add((Button)findViewById(R.id.P2Card10));
	        	p2Cards.add((Button)findViewById(R.id.P2Card11));
	        	p2Cards.add((Button)findViewById(R.id.P2Card12));
	        	break;
	    	case 3:
	    		p2Name = (TextView)findViewById(R.id.P2Name);
	        	p2Score = (TextView)findViewById(R.id.P2CurrentScore);
	        	p3Name = (TextView)findViewById(R.id.P3Name);
	        	p3Score = (TextView)findViewById(R.id.P3CurrentScore);
	        	cards = new ArrayList<Button>();
	        	cards.add((Button)findViewById(R.id.Card1));
	        	cards.add((Button)findViewById(R.id.Card2));
	        	cards.add((Button)findViewById(R.id.Card3));
	        	cards.add((Button)findViewById(R.id.Card4));
	        	cards.add((Button)findViewById(R.id.Card5));
	        	cards.add((Button)findViewById(R.id.Card6));
	        	cards.add((Button)findViewById(R.id.Card7));
	        	cards.add((Button)findViewById(R.id.Card8));
	        	cards.add((Button)findViewById(R.id.Card9));
	        	cards.add((Button)findViewById(R.id.Card10));
	        	p2Cards = new ArrayList<Button>();
	        	p2Cards.add((Button)findViewById(R.id.P2Card1));
	        	p2Cards.add((Button)findViewById(R.id.P2Card2));
	        	p2Cards.add((Button)findViewById(R.id.P2Card3));
	        	p2Cards.add((Button)findViewById(R.id.P2Card4));
	        	p2Cards.add((Button)findViewById(R.id.P2Card5));
	        	p2Cards.add((Button)findViewById(R.id.P2Card6));
	        	p2Cards.add((Button)findViewById(R.id.P2Card7));
	        	p2Cards.add((Button)findViewById(R.id.P2Card8));
	        	p2Cards.add((Button)findViewById(R.id.P2Card9));
	        	p2Cards.add((Button)findViewById(R.id.P2Card10));
	        	p3Cards = new ArrayList<Button>();
	        	p3Cards.add((Button)findViewById(R.id.P3Card1));
	        	p3Cards.add((Button)findViewById(R.id.P3Card2));
	        	p3Cards.add((Button)findViewById(R.id.P3Card3));
	        	p3Cards.add((Button)findViewById(R.id.P3Card4));
	        	p3Cards.add((Button)findViewById(R.id.P3Card5));
	        	p3Cards.add((Button)findViewById(R.id.P3Card6));
	        	p3Cards.add((Button)findViewById(R.id.P3Card7));
	        	p3Cards.add((Button)findViewById(R.id.P3Card8));
	        	p3Cards.add((Button)findViewById(R.id.P3Card9));
	        	p3Cards.add((Button)findViewById(R.id.P3Card10));
	        	break;
	    	case 4:
	    		p2Name = (TextView)findViewById(R.id.P2Name);
	        	p2Score = (TextView)findViewById(R.id.P2CurrentScore);
	        	p3Name = (TextView)findViewById(R.id.P3Name);
	        	p3Score = (TextView)findViewById(R.id.P3CurrentScore);
	        	p4Name = (TextView)findViewById(R.id.P4Name);
	        	p4Score = (TextView)findViewById(R.id.P4CurrentScore);
	        	cards = new ArrayList<Button>();
	        	cards.add((Button)findViewById(R.id.Card1));
	        	cards.add((Button)findViewById(R.id.Card2));
	        	cards.add((Button)findViewById(R.id.Card3));
	        	cards.add((Button)findViewById(R.id.Card4));
	        	cards.add((Button)findViewById(R.id.Card5));
	        	cards.add((Button)findViewById(R.id.Card6));
	        	cards.add((Button)findViewById(R.id.Card7));
	        	cards.add((Button)findViewById(R.id.Card8));
	        	p2Cards = new ArrayList<Button>();
	        	p2Cards.add((Button)findViewById(R.id.P2Card1));
	        	p2Cards.add((Button)findViewById(R.id.P2Card2));
	        	p2Cards.add((Button)findViewById(R.id.P2Card3));
	        	p2Cards.add((Button)findViewById(R.id.P2Card4));
	        	p2Cards.add((Button)findViewById(R.id.P2Card5));
	        	p2Cards.add((Button)findViewById(R.id.P2Card6));
	        	p2Cards.add((Button)findViewById(R.id.P2Card7));
	        	p2Cards.add((Button)findViewById(R.id.P2Card8));
	        	p3Cards = new ArrayList<Button>();
	        	p3Cards.add((Button)findViewById(R.id.P3Card1));
	        	p3Cards.add((Button)findViewById(R.id.P3Card2));
	        	p3Cards.add((Button)findViewById(R.id.P3Card3));
	        	p3Cards.add((Button)findViewById(R.id.P3Card4));
	        	p3Cards.add((Button)findViewById(R.id.P3Card5));
	        	p3Cards.add((Button)findViewById(R.id.P3Card6));
	        	p3Cards.add((Button)findViewById(R.id.P3Card7));
	        	p3Cards.add((Button)findViewById(R.id.P3Card8));
	        	p4Cards = new ArrayList<Button>();
	        	p4Cards.add((Button)findViewById(R.id.P4Card1));
	        	p4Cards.add((Button)findViewById(R.id.P4Card2));
	        	p4Cards.add((Button)findViewById(R.id.P4Card3));
	        	p4Cards.add((Button)findViewById(R.id.P4Card4));
	        	p4Cards.add((Button)findViewById(R.id.P4Card5));
	        	p4Cards.add((Button)findViewById(R.id.P4Card6));
	        	p4Cards.add((Button)findViewById(R.id.P4Card7));
	        	p4Cards.add((Button)findViewById(R.id.P4Card8));
	        	break;
	        default:
	        	break;
	    }
    	
    	//Find userName text field
    	userName = (TextView)findViewById(R.id.UserName);
    	currentScore = (TextView)findViewById(R.id.CurrentScore);
    }
    
    /*
     * Initializes game starting conditions and prompts the user with how many cards to turn face up
     */
    private void startGame(){
    	score = new Score();
    	
    	// set up drawables HashMap
    	setDrawablesMap();
        
        //Create a new game with all players
        game = new Game(playerNames.size(), playerNames);
        
        setupPlayerNames();
        
        //Display top of the discard Pile
        updateDiscardField();
        
        //Set up card buttons for turning cards face up
        gameObjectivesPrompt();
        
    }
    
    private void gameObjectivesPrompt(){
    	AlertDialog.Builder objectives = new AlertDialog.Builder(this);
    	
    	objectives.setTitle("Game Objectives");
    	objectives.setMessage("The objective of this game \nis to match amino acids vertically. \nTo acheive the highest score possible, \nmatch amino acids based on their similarity.");

    	objectives.setPositiveButton("Continue", new DialogInterface.OnClickListener() {
		public void onClick(DialogInterface dialog, int whichButton) {
	        initCardButtons();
		}});
    	objectives.show();
    }
    
    /*
     * Sets the players names into the appropriate text views at the start of the game
     */
    private void setupPlayerNames(){
    	switch(game.getPlayers().size()){
    		case 2:
    			p2Name.setText(game.getPlayers().get(1).getUserName());
    			break;
    		case 3:
    			p2Name.setText(game.getPlayers().get(1).getUserName());
    			p3Name.setText(game.getPlayers().get(2).getUserName());
    			break;
    		case 4:
    			p2Name.setText(game.getPlayers().get(1).getUserName());
    			p3Name.setText(game.getPlayers().get(2).getUserName());
    			p4Name.setText(game.getPlayers().get(3).getUserName());
    			break;
    	}
    	
    	userName.setText(game.getPlayers().get(0).getUserName());
    	
    }
    
	@Override
    protected void onStart(){
    	super.onStart();
    }
    @Override
    protected void onResume() {
        super.onResume();
    }
    @Override
    protected void onPause() {
        super.onPause();
    }
    @Override
    protected void onStop() {
        super.onStop();
    }
    @Override
    protected void onDestroy() {
        super.onDestroy();
    }

    
    /*
     * Find the ids for all of the card buttons add them to the cards arraylist
     * and set their on click listeners
     */
    private void initCardButtons(){
    	// cycles through the players
    	if(currentPlayer < game.getPlayers().size()){
	        //Inform users of how many cards they can turn face up
	        AlertDialog.Builder turnCardsFaceUp = new AlertDialog.Builder(this);
	
			turnCardsFaceUp.setTitle(playerNames.get(currentPlayer) + "'s Turn");
			turnCardsFaceUp.setMessage("Tap " +  Math.round(numOfCardsToDraw * 0.8) + " cards to turn them face up.");
	
			turnCardsFaceUp.setPositiveButton("Ok", new DialogInterface.OnClickListener() {
			public void onClick(DialogInterface dialog, int whichButton) {}});
			turnCardsFaceUp.show();
				
	    	
	    	for(int i = 0; i < cards.size(); i++){
	    		final PlayerAndCard p = new PlayerAndCard(currentPlayer,i);
	    		cards.get(i).setOnClickListener(new Button.OnClickListener(){
	    			public void onClick(View v) {
	    				initCards(p.getPlayerNum(), p.getCardNum());
	    			}});
	    	}
    	}else{
    		currentPlayer = 0;
    		turn();
    	}
    }
    
    /*
     * Sets the card buttons text to the card located at that position in the 
     * players hand and when X cards are turned up, disable the card buttons and start the turn phase
     */
    private void initCards(int player, int cardPos){
    	// if the selected card is face-down
    	if(game.getPlayers().get(player).getPlayersHand().getCardTurn(cardPos) == false) {
    		// get the amino acid of that card
    		String amino = game.getPlayers().get(player).getPlayersHand().getCard(cardPos).getAminoAcid();
    		// set the image of that card
			cards.get(cardPos).setBackgroundDrawable(getResources().getDrawable(drawables.get(amino)));
			// set the new card
			game.getPlayers().get(player).getPlayersHand().setCardTurn(cardPos);
			// increment the number of cards the player has picked
			game.getPlayers().get(player).incrementCardsPicked();
			// if the current player has turned the initial cards face-up, end the turn
			if(game.getPlayers().get(player).getCardsPicked() >= Math.round(numOfCardsToDraw * 0.8)) {
				currentPlayer += 1; // increment current player so it becomes the next player's turn
				disableCardButtons();
				refreshDisplay();
				initCardButtons();
			}
    	}
    }
    
    /*
     * Refreshes the display based on number of players
     */
    private void refreshDisplay(){ 	
    	switch(game.getPlayers().size()){
			case 2:
				updateDisplayForTwo();
				break;
			case 3:
				updateDisplayForThree();
				break;
			case 4:
				updateDisplayForFour();
				break;
		}
    }
    
    /*
     * Grabs all the games players for two player mode and sets them based on the current player
     */
    private void updateDisplayForTwo(){
    	ArrayList<Player> p = game.getPlayers();
    	for(int j = 0; j < p.size(); j++){
    		p.get(j).updateScore(score);
    	}
    	
    	switch(currentPlayer){
    		case 1:
    			displayTwo(1,0,p);
    			break;
    		default:
    			displayTwo(0,1,p);
    			break;
    	}
    }
    
    /*
     * Grabs all the games players for three player mode and sets them based on the current player
     */
    private void updateDisplayForThree(){
    	ArrayList<Player> p = game.getPlayers();
    	for(int j = 0; j < p.size(); j++){
    		p.get(j).updateScore(score);
    	}
    	
    	switch(currentPlayer){
    		case 1:
    			displayThree(1,2,0,p);
				break;
    		case 2:
    			displayThree(2,0,1,p);
    			break;
			default:
				displayThree(0,1,2,p);
				break;
    	}
    }
    
    /*
     * Grabs all the games players for four player mode and sets them based on the current player
     */
    private void updateDisplayForFour(){
    	ArrayList<Player> p = game.getPlayers();
    	for(int j = 0; j < p.size(); j++){
    		p.get(j).updateScore(score);
    	}
    	
    	switch(currentPlayer){
    		case 1:
    			displayFour(1,2,3,0,p);
    			break;
    		case 2:
    			displayFour(2,3,0,1,p);
    			break;
    		case 3:
    			displayFour(3,0,1,2,p);
    			break;
    		default:
    			displayFour(0,1,2,3,p);
    			break;
    	}
    }
    
    /*
     * Does the actual switching of the player cards buttons for two player mode
     */
    private void displayTwo(int curr, int p2, ArrayList<Player> p){
    	p2Name.setText(p.get(p2).getUserName());
		p2Score.setText(p.get(p2).getScore() + "");
		userName.setText(p.get(curr).getUserName());
		currentScore.setText(p.get(curr).getScore() + "");
		for(int i = 0; i < p.get(0).getPlayersHand().size(); i++){
			if(p.get(p2).getPlayersHand().getCardTurn(i)){
				String amino = p.get(p2).getPlayersHand().getCard(i).getAminoAcid();
				p2Cards.get(i).setBackgroundDrawable(getResources().getDrawable(drawables.get(amino)));
			}else{
				p2Cards.get(i).setBackgroundDrawable(getResources().getDrawable(drawables.get("Background")));
			}
			
			if(p.get(curr).getPlayersHand().getCardTurn(i)){
				String amino = p.get(curr).getPlayersHand().getCard(i).getAminoAcid();
				cards.get(i).setBackgroundDrawable(getResources().getDrawable(drawables.get(amino)));
			}else{
				cards.get(i).setBackgroundDrawable(getResources().getDrawable(drawables.get("Background")));
			}
		}
    }
    
    /*
     * Does the actual switching of the player cards buttons for three player mode
     */
    private void displayThree(int curr, int p2, int p3, ArrayList<Player> p){
    	p3Name.setText(p.get(p3).getUserName());
		p3Score.setText(p.get(p3).getScore() + "");
		p2Name.setText(p.get(p2).getUserName());
		p2Score.setText(p.get(p2).getScore() + "");
		userName.setText(p.get(curr).getUserName());
		currentScore.setText(p.get(curr).getScore() + "");
		for(int i = 0; i < p.get(0).getPlayersHand().size(); i++){
			if(p.get(p3).getPlayersHand().getCardTurn(i)){
				String amino = p.get(p3).getPlayersHand().getCard(i).getAminoAcid();
				p3Cards.get(i).setBackgroundDrawable(getResources().getDrawable(drawables.get(amino)));
			}else{
				p3Cards.get(i).setBackgroundDrawable(getResources().getDrawable(drawables.get("Background")));
			}
			
			if(p.get(p2).getPlayersHand().getCardTurn(i)){
				String amino = p.get(p2).getPlayersHand().getCard(i).getAminoAcid();
				p2Cards.get(i).setBackgroundDrawable(getResources().getDrawable(drawables.get(amino)));
			}else{
				p2Cards.get(i).setBackgroundDrawable(getResources().getDrawable(drawables.get("Background")));
			}
			
			if(p.get(curr).getPlayersHand().getCardTurn(i)){
				String amino = p.get(curr).getPlayersHand().getCard(i).getAminoAcid();
				cards.get(i).setBackgroundDrawable(getResources().getDrawable(drawables.get(amino)));
			}else{
				cards.get(i).setBackgroundDrawable(getResources().getDrawable(drawables.get("Background")));
			}
		}
    }
    
    /*
     * Does the actual switching of the player cards buttons for four player mode
     */
    private void displayFour(int curr, int p2, int p3, int p4, ArrayList<Player> p){
    	p4Name.setText(p.get(p4).getUserName());
		p4Score.setText(p.get(p4).getScore() + "");
		p3Name.setText(p.get(p3).getUserName());
		p3Score.setText(p.get(p3).getScore() + "");
		p2Name.setText(p.get(p2).getUserName());
		p2Score.setText(p.get(p2).getScore() + "");
		userName.setText(p.get(curr).getUserName());
		currentScore.setText(p.get(curr).getScore() + "");
		for(int i = 0; i < p.get(0).getPlayersHand().size(); i++){
			if(p.get(p4).getPlayersHand().getCardTurn(i)){
				String amino = p.get(p4).getPlayersHand().getCard(i).getAminoAcid();
				p4Cards.get(i).setBackgroundDrawable(getResources().getDrawable(drawables.get(amino)));
			}else{
				p4Cards.get(i).setBackgroundDrawable(getResources().getDrawable(drawables.get("Background")));
			}
			
			if(p.get(p3).getPlayersHand().getCardTurn(i)){
				String amino = p.get(p3).getPlayersHand().getCard(i).getAminoAcid();
				p3Cards.get(i).setBackgroundDrawable(getResources().getDrawable(drawables.get(amino)));
			}else{
				p3Cards.get(i).setBackgroundDrawable(getResources().getDrawable(drawables.get("Background")));
			}
			
			if(p.get(p2).getPlayersHand().getCardTurn(i)){
				String amino = p.get(p2).getPlayersHand().getCard(i).getAminoAcid();
				p2Cards.get(i).setBackgroundDrawable(getResources().getDrawable(drawables.get(amino)));
			}else{
				p2Cards.get(i).setBackgroundDrawable(getResources().getDrawable(drawables.get("Background")));
			}
			
			if(p.get(curr).getPlayersHand().getCardTurn(i)){
				String amino = p.get(curr).getPlayersHand().getCard(i).getAminoAcid();
				cards.get(i).setBackgroundDrawable(getResources().getDrawable(drawables.get(amino)));
			}else{
				cards.get(i).setBackgroundDrawable(getResources().getDrawable(drawables.get("Background")));
			}
		}
    }
    
    /*
     * Sets the onClick listeners of all the card buttons to nothing
     */
    private void disableCardButtons(){
    	for(int card = 0; card < cards.size(); card++){
    		cards.get(card).setOnClickListener(new Button.OnClickListener(){
    			public void onClick(View v){}
    		});
    	}
    }
    /*
     * Sets the card buttons to replace cards in the hand based on based on the card clicked
     */
    private void enableCardButtons(int player){
    	for(int i = 0; i < cards.size(); i++){
    		final PlayerAndCard p = new PlayerAndCard(player,i);
    		cards.get(i).setOnClickListener(new Button.OnClickListener(){
    			public void onClick(View v) {
    				setCard(p.getPlayerNum(),p.getCardNum());
    			}});
    	}
    }
    
    /*
     * Sets the card of a players hand based on whether the deck or discard pile
     */
    private void setCard(int player, int cardPosition){
    	//If the deck was clicked
    	if(deckClicked){
    		//Grabs the current card in the players hand based on the card clicked
			Card currentCard = game.getPlayers().get(player).getPlayersHand().getCard(cardPosition);
			
			//Replace that place in the hand with the top of the deck
			game.getPlayers().get(player).getPlayersHand().replaceCard(game.getDeck().drawCard(), cardPosition);
			
			//Push the card replaced on top of the discard pile
			game.getDiscardPile().pushCard(currentCard);
			
			//Set the DiscardPile button to the new top of the discardPile
			DiscardPile.setBackgroundDrawable(getResources().getDrawable(drawables.get(game.getDiscardPile().peekAtTop().getAminoAcid())));
			
			//If the card was face down, increment the number of cards now face up
			if(game.getPlayers().get(player).getPlayersHand().getCardTurn(cardPosition) == false) {
				game.getPlayers().get(player).getPlayersHand().setCardTurn(cardPosition);
				game.getPlayers().get(player).incrementCardsPicked();
			}
			
			//Set the card button to the new card located at that position in the hand
			cards.get(cardPosition).setBackgroundDrawable(getResources().getDrawable(drawables.get(game.getPlayers().get(player).getPlayersHand().getCard(cardPosition).getAminoAcid())));

			if(game.getDeck().isEmpty()){
				Deck.setBackgroundDrawable(getResources().getDrawable(R.drawable.outline));
			}else{
				Deck.setBackgroundDrawable(getResources().getDrawable(R.drawable.parkside_back1));
			}
			
			//Disable the card buttons
			disableCardButtons();
			
			//Disable the discard button so it cant be clicked again until the next turn
			disableDiscard();
		}else{
			
			//Get the current card at the position clicked in the players hand
			Card currentCard = game.getPlayers().get(player).getPlayersHand().getCard(cardPosition);
			
			//Replace that card with the top card of the discard pile
			game.getPlayers().get(player).getPlayersHand().replaceCard(game.getDiscardPile().drawCard(), cardPosition);
			
			//Update the discard pile
			game.getDiscardPile().pushCard(currentCard);
			
			//Set the new text of the top card of the discard Pile
			DiscardPile.setBackgroundDrawable(getResources().getDrawable(drawables.get(game.getDiscardPile().peekAtTop().getAminoAcid())));
			
			//If the card was face down, increment the number of cards now face up
			if(game.getPlayers().get(player).getPlayersHand().getCardTurn(cardPosition) == false) {
				game.getPlayers().get(player).getPlayersHand().setCardTurn(cardPosition);
				game.getPlayers().get(player).incrementCardsPicked();
			}
			
			//Set text of the card at the position clicked
			cards.get(cardPosition).setBackgroundDrawable(getResources().getDrawable(drawables.get(game.getPlayers().get(player).getPlayersHand().getCard(cardPosition).getAminoAcid())));

			//Disable Card buttons
			disableCardButtons();
			//Disable discard buttons
			disableDiscard();
		}
    	
    	prepForNextTurn();
    	//Call next turn
    	turn();
    }
    
    /*
     * Disable discardPile
     */
    private void disableDeck(){
    	Deck.setOnClickListener(new Button.OnClickListener(){
			public void onClick(View v) {
			}});
    }
    
    /*
     * Initializes Controls at the beginning of the turn
     */
    private void initControls(){
    	//Ends game and scores when all cards are face up and displays score
    	if(game.getPlayers().get(currentPlayer).getCardsPicked() >= cardsToEnd){
    		endGame();
    	}
    	else {
    		//Set the onclick listener of the deck
    		Deck.setOnClickListener(new Button.OnClickListener(){
    			public void onClick(View v) {
    				disableKnock();
    				deckClicked = true;
    				//If the deck isn't empty, display top card of deck and enable card buttons
    				if(!game.getDeck().isEmpty()) {
    					Deck.setBackgroundDrawable(getResources().getDrawable(drawables.get(game.getDeck().peekAtTop().getAminoAcid())));
    					deckClicked();
    					enableCardButtons(currentPlayer);
    				//If the deck is emptied, end the game and display the score
    				} else {
    					endGame();
    				}
    			}});
    		//Set the onClick listener of the discard pile
    		DiscardPile.setOnClickListener(new Button.OnClickListener(){
    			//If the discard pile is clicked at start of turn, disable the deck and disable the discard pile
    			//Then enable all card buttons
    			public void onClick(View v) {
    				disableKnock();
    				if(game.getPlayers().get(currentPlayer).getFirstDiscard() && tutorialMode){
    		    		discardClicked();
    		    	}
    				deckClicked = false;
    				if(game.getDiscardPile().peekAtTop() != null){
    					disableDeck();
    					disableDiscard();
    					enableCardButtons(currentPlayer);
    				}else{
    					DiscardPile.setBackgroundDrawable(getResources().getDrawable(R.drawable.outline));
    				}
    			}});
    		
    		if(knockInitiated){
    			knock.setOnClickListener(new Button.OnClickListener(){
        			public void onClick(View v) {
        				//prepForNextTurn();
	    				//turn();
        			}});
    		}else{
	    		knock.setOnClickListener(new Button.OnClickListener(){
	    			//If the discard pile is clicked at start of turn, disable the deck and disable the discard pile
	    			//Then enable all card buttons
	    			public void onClick(View v) {
	    				game.knock(game.getPlayers().get(currentPlayer));
	    				game.getPlayers().get(currentPlayer).setCardsPicked(cardsToEnd);
	    				knockInitiated = true;
	    				//knock.setText("Knocked");
	    				prepForNextTurn();
	    				turn();
	    			}});
    		}
    	}
    }
    
    /*
     * Prompt for first time discard is clicked per player
     */
    private void discardClicked(){
    		AlertDialog.Builder discardSelected = new AlertDialog.Builder(this);

    		discardSelected.setTitle("Pick a card to replace");
    		discardSelected.setMessage("Tap one of your cards to replace with top card of discard pile.");

    		discardSelected.setPositiveButton("Ok", new DialogInterface.OnClickListener() {
    		public void onClick(DialogInterface dialog, int whichButton) {}});
    		discardSelected.show();	
    		game.getPlayers().get(currentPlayer).setFirstDiscard(false);
    }
    
    /*
     * If the deck is clicked, disable the deck and set the discard pile so that you can discard from the
     * top of the deck
     */
    private void deckClicked(){
    	if(game.getPlayers().get(currentPlayer).getFirstDraw() && tutorialMode){
    		AlertDialog.Builder deckSelected = new AlertDialog.Builder(this);

    		deckSelected.setTitle("Pick a card to replace or discard");
    		deckSelected.setMessage("Tap one of your cards to replace drawn card or tap the discard pile to discard drawn card.");

    		deckSelected.setPositiveButton("Ok", new DialogInterface.OnClickListener() {
    		public void onClick(DialogInterface dialog, int whichButton) {}});
    		deckSelected.show();	
    		game.getPlayers().get(currentPlayer).setFirstDraw(false);
    	}
    	Deck.setOnClickListener(new Button.OnClickListener(){
			public void onClick(View v) {
			}});
    	DiscardPile.setOnClickListener(new Button.OnClickListener(){
			public void onClick(View v) {
				game.getDiscardPile().pushCard(game.getDeck().drawCard());
				if(game.getDeck().isEmpty()){
					Deck.setBackgroundDrawable(getResources().getDrawable(R.drawable.outline));
				}else{
					Deck.setBackgroundDrawable(getResources().getDrawable(R.drawable.parkside_back1));
				}
				DiscardPile.setBackgroundDrawable(getResources().getDrawable(drawables.get(game.getDiscardPile().peekAtTop().getAminoAcid())));
				disableDiscard();
				disableCardButtons();
				prepForNextTurn();
				turn();
			}});
    }
    
    /*
     * Displays knock button
     */
    private void disableKnock(){
    	knock.setOnClickListener(new Button.OnClickListener(){
			public void onClick(View v) {
			}});
    }
    
    /*
     * Used before turn is called to change the currentplayer and refresh the display
     */
    private void prepForNextTurn(){
    	if(game.getPlayers().size() - 1 > currentPlayer){
    		currentPlayer++;
    	}else{
    		currentPlayer = 0;
    	}
    	
    	refreshDisplay();
    }
    
    /*
     * Disables discard
     */
    private void disableDiscard(){
    	DiscardPile.setOnClickListener(new Button.OnClickListener(){
			public void onClick(View v) {
			}});
    }
    
    /*
     * Updates text of the discard pile
     */
    private void updateDiscardField(){
    	Button discard = (Button)findViewById(R.id.DiscardPile);
    	discard.setBackgroundDrawable(getResources().getDrawable(drawables.get(game.getDiscardPile().peekAtTop().getAminoAcid())));
    }
    /*
     * This method creates the drawables HashMap
     */
    private void setDrawablesMap() {
    	drawables.put("A", R.drawable.a_card);
    	drawables.put("C", R.drawable.c_card);
    	drawables.put("D", R.drawable.d_card);
    	drawables.put("E", R.drawable.e_card);
    	drawables.put("F", R.drawable.f_card);
    	drawables.put("G", R.drawable.g_card);
    	drawables.put("H", R.drawable.h_card);
    	drawables.put("I", R.drawable.i_card);
    	drawables.put("K", R.drawable.k_card);
    	drawables.put("L", R.drawable.l_card);
    	drawables.put("M", R.drawable.m_card);
    	drawables.put("N", R.drawable.n_card);
    	drawables.put("P", R.drawable.p_card);
    	drawables.put("Q", R.drawable.q_card);
    	drawables.put("R", R.drawable.r_card);
    	drawables.put("S", R.drawable.s_card);
    	drawables.put("T", R.drawable.t_card);
    	drawables.put("V", R.drawable.v_card);
    	drawables.put("W", R.drawable.w_card);
    	drawables.put("Y", R.drawable.y_card);
    	drawables.put("Background", R.drawable.parkside_back1);
    }
    
    /*
     * Initializes the controls
     */
    private void turn(){    	
        AlertDialog.Builder turn = new AlertDialog.Builder(this);

        turn.setTitle("Begin Turn");
        turn.setMessage(playerNames.get(currentPlayer) + "'s Turn");

        turn.setPositiveButton("Ok", new DialogInterface.OnClickListener() {
		public void onClick(DialogInterface dialog, int whichButton) {}});
        turn.show();
    	
    	if(game.getPlayers().get(currentPlayer).getFirstTurn() && tutorialMode){
    		AlertDialog.Builder selectPile = new AlertDialog.Builder(this);

    		selectPile.setTitle("Select a Card from the Deck or Discard Pile");
    		selectPile.setMessage("Tap the deck to draw a card or tap the discard pile to use the top card from the discard pile.");

    		selectPile.setPositiveButton("Ok", new DialogInterface.OnClickListener() {
    		public void onClick(DialogInterface dialog, int whichButton) {}});
    		selectPile.show();
    		game.getPlayers().get(currentPlayer).setFirstTurn(false);
    	}
    	initControls();
    }
    
    /*
     * Scores the hand of all the players and computes the highest score
     */
    private void endGame() {
        ArrayList<Player> playersList = game.getPlayers(); // get the list of players
        // cylce through the list of players
        for(int i = 0; i < playersList.size(); i++) {
            // cycle through the player's hand
            for(int j = 0; j < playersList.get(i).getPlayersHand().getTurnUp().length; j++) {
                // turn up the face-down cards
                if(!playersList.get(i).getPlayersHand().getTurnUp()[j]) {
                    game.getPlayers().get(i).getPlayersHand().setCardTurn(j);
                }
            }
        }
        
        refreshDisplay();
        
        
        AlertDialog.Builder scoreBoard = new AlertDialog.Builder(this);
        scoreBoard.setTitle("Score Board");
        
        scoreBoard.setMessage(scoreGame(playersList));

        scoreBoard.setPositiveButton("Ok", new DialogInterface.OnClickListener() {
        public void onClick(DialogInterface dialog, int whichButton) {
            finish();
        }});
            
        scoreBoard.show();
    }
    
    /*
     * Partition for quicksort
     */
    private int partition(Player arr[], int left, int right){
          int i = left, j = right;
          Player tmp;
          int pivot = arr[(left + right) / 2].getScore();
         
          while (i <= j) {
                while (arr[i].getScore() < pivot){
                      i++;
                }
                while (arr[j].getScore() > pivot){
                      j--;
                }
                if (i <= j) {
                      tmp = arr[i];
                      arr[i] = arr[j];
                      arr[j]= tmp;
                      i++;
                      j--;
                }
          }

          return i;
    }

    /*
     * Quick sort algorithm
     */
    private Player[] quickSort(Player arr[], int left, int right) {
          int index = partition(arr, left, right);

          if (left < index - 1){
                quickSort(arr, left, index - 1);
          }
          if (index < right){
              quickSort(arr, index, right);
          }
          
          return arr;
    } 
    
    /*
     * Scores the game and returns a string formatted like
     * 1. playername: score
     * 2. playername2: score
     * etc...
     */
    private String scoreGame(ArrayList<Player> playersList){
    	Player players[] = new Player[playersList.size()];  // array of players for sorting
        
        // fill the array with the players
        for(int i = 0; i < playersList.size(); i++) {
            players[i]  = playersList.get(i);
        }

        // sort the players based on their score
        players = quickSort(players, 0, players.length - 1);
        int highScore = players[0].getScore(); // get the game's high score
        
        // cycle through the players
        for(int i = 0; i < players.length; i++) {
            if( highScore > players[i].getScore() ) {
            
                // if the knocking player does not have the highest score, halve it
                if( players[i].getUserName().equals(game.getKnockingPlayer())) {
                    players[i].setScore(players[i].getScore() - Math.abs(players[i].getScore() / 2) );
                    break;
                }
            }
        }
        
        players = quickSort(players, 0, players.length - 1);    // update the ranking
        
        String scoreString = "";    // string of scores to be displayed at the end
        int currentPlace = 0;    // the player's place
        int lastScore = 200;    // last player's score
        
        for(int i = players.length - 1; i > -1; i--) {
            int tempScore = players[i].getScore();
            if(tempScore < lastScore)
                currentPlace++;
            scoreString += currentPlace + ". " + players[i].getUserName() + ": " + tempScore + "\n";
            lastScore = tempScore;
        }
    	return scoreString;
    }
}
